package com.leyou.order.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.order.dto.CartDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.entity.Order;
import com.leyou.order.entity.OrderDetail;
import com.leyou.order.entity.OrderLogistics;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.order.utils.UserHolder;
import com.leyou.order.vo.OrderDetailVO;
import com.leyou.order.vo.OrderLogisticsVO;
import com.leyou.order.vo.OrderVO;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 虎哥
 */
@Slf4j
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper detailMapper;

    @Autowired
    private OrderLogisticsMapper logisticsMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private UserClient userClient;

    @Transactional
    public long createOrder(OrderDTO orderDTO) {
        // 1.订单数据
        Order order = new Order();
        // 1.1.订单编号（不是自增长，需要自己生成）
        long orderId = idWorker.nextId();
        order.setOrderId(orderId);
        // 1.2.订单金额
        List<CartDTO> carts = orderDTO.getCarts();
        // 1.2.1.获取商品id
        Map<Long, Integer> numMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
        List<Long> idList = new ArrayList<>(numMap.keySet());
        // 1.2.2.根据id查询商品
        List<SkuDTO> skuList = itemClient.querySkuByIds(idList);
        // 1.2.3.创建detail集合
        List<OrderDetail> detailList = new ArrayList<>();
        // 1.2.3.计算总金额
        long total = 0;
        for (SkuDTO sku : skuList) {
            // 计算金额
            Integer num = numMap.get(sku.getId());
            total += sku.getPrice() * num;
            // 封装成orderDetail
            OrderDetail detail = new OrderDetail();
            detailList.add(detail);
            detail.setTitle(sku.getTitle());
            detail.setSkuId(sku.getId());
            detail.setPrice(sku.getPrice());
            detail.setNum(num);
            detail.setOwnSpec(sku.getOwnSpec());
            detail.setImage(StringUtils.substringBefore(sku.getImages(), ","));
            detail.setOrderId(orderId);
        }
        order.setTotalFee(total);
        order.setPostFee(0L);
        order.setActualFee(order.getTotalFee() + order.getPostFee());
        order.setPaymentType(orderDTO.getPaymentType());
        // 1.3.用户id
        Long userId = UserHolder.getUser().getId();
        order.setUserId(userId);
        // 1.4.状态
        order.setStatus(OrderStatusEnum.INIT.value());
        orderMapper.insertSelective(order);

        // 2.订单详情
        detailMapper.insertList(detailList);

        // 3.订单物流
        Long addressId = orderDTO.getAddressId();
        // 3.1.根据id，查询物流信息
        AddressDTO addressDTO = userClient.queryAddressById(userId, addressId);
        // 3.2.封装到OrderLogistic
        OrderLogistics logistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
        logistics.setOrderId(orderId);
        logisticsMapper.insertSelective(logistics);

        // 4.减库存
        try {
            itemClient.minusStock(numMap);
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH);
        }

        return orderId;
    }

    public OrderVO queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order == null) {
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);
        // 2.查询订单详情
        orderVO.setDetailList(queryDetailByOrderId(orderId));
        // 3.查询物流
        orderVO.setLogistics(queryLogisticsByOrderId(orderId));
        return orderVO;
    }

    private OrderLogisticsVO queryLogisticsByOrderId(Long orderId) {
        OrderLogistics logistics = logisticsMapper.selectByPrimaryKey(orderId);
        if (logistics == null) {
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return BeanHelper.copyProperties(logistics, OrderLogisticsVO.class);
    }

    private List<OrderDetailVO> queryDetailByOrderId(Long orderId) {
        OrderDetail detail = new OrderDetail();
        detail.setOrderId(orderId);
        List<OrderDetail> list = detailMapper.select(detail);
        if (CollectionUtils.isEmpty(list)) {
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(list, OrderDetailVO.class);
    }

    @Autowired
    private PayHelper payHelper;

    public String getPayUrl(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order == null) {
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        // 2.验证订单状态
        if (!Objects.equals(order.getStatus(), OrderStatusEnum.INIT.value())) {
            // 无效的订单状态
            throw new LyException(ExceptionEnum.INVALID_ORDER_STATUS);
        }
        // 3.获取支付地址
        return payHelper.getPayUrl(orderId, order.getActualFee(), "乐优商城");
    }

    public void handleNotify(Map<String, String> data) {
        // 1.校验数据签名
        payHelper.isSignatureValid(data);
        // 2.校验订单金额
        // 2.1.去除请求参数中的订单和金额
        String total_fee = data.get("total_fee");
        String out_trade_no = data.get("out_trade_no");
        if (StringUtils.isEmpty(total_fee) || StringUtils.isEmpty(out_trade_no)) {
            // 请求参数有误
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        // 2.2.查询数据库中的订单金额
        Long orderId = Long.valueOf(out_trade_no);
        Order order = orderMapper.selectByPrimaryKey(orderId);
        // 2.3.校验金额
        if (!order.getActualFee().toString().equals(total_fee)) {
            // 请求参数有误
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        // 3.校验数据幂等性
        if (!Objects.equals(order.getStatus(), OrderStatusEnum.INIT.value())) {
            // 订单已经处理过，放弃操作
            return;
        }
        // 4.修改订单状态为已支付 update tb_order set status=2 and pay_time=1231 where order_id = 101 and status=1
        Example example = new Example(Order.class);
        example.createCriteria()
                // 订单编号
                .andEqualTo("orderId", orderId)
                // 状态条件，乐观锁
                .andEqualTo("status", OrderStatusEnum.INIT.value());

        Order record = new Order();
        record.setStatus(OrderStatusEnum.PAY_UP.value());
        record.setPayTime(new Date());

        orderMapper.updateByExampleSelective(record, example);

        log.info("微信支付通知处理成功！订单id：{}", orderId);
    }

    public Integer queryOrderState(Long orderId) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if(order == null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }
}
